import numpy as np
from sklearn.datasets import load_digits
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import adjusted_rand_score
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import classification_report, confusion_matrix

digits = load_digits()
data=digits.data
label=digits.target
N=len(data)
N_train=int(N*0.8)
N_test=N-N_train
x_train=data[:N_train]
x_test=data[N_train:,:]
y_train=label[:N_train]
y_test=label[N_train:]

#自己写的
def sigmoid(x):
    return 1.0 / (1 + np.exp(-x))

class Logistic(object):
    """logistic回归模型"""
    def __init__(self, data, label):
        self.data = data
        self.label = label
        self.weights=[]
        self.b = []
        # FIXME: n -> d
        self.data_num, n = np.shape(data)
        self.weights=np.ones((10,n))
        self.b=np.ones(n)

    def train(self, times=150):
        # 学习速率
        step = 0.01
        t=np.zeros(len(self.label))
        print("start")
        for k in range(10):
            print(k)
            t=np.zeros(len(self.label))
            t[np.where(self.label==k)] = 1
            for j in range(times):
                data_index = list(range(self.data_num))
                for i in range(self.data_num):
                    rand_index = int(np.random.uniform(0, len(data_index)))
                    error = t[rand_index] - sigmoid(sum(self.data[rand_index] * self.weights[k] + self.b[k]))
                    self.weights[k] += step * error * self.data[rand_index]
                    self.b[k] += step * error
                    del(data_index[rand_index])
        print("end")

    def predict(self, predict_data):
        """预测函数"""
        sumj=0
        max_sum=-1
        max_index=-1
        index_list=[]
        for i in range(len(predict_data)):
            sumj=0
            max_sum=-100
            max_index=-1
            for j in range(10):
                sumj=sum(self.weights[j] * predict_data[i] + self.b[j])
                if sumj>max_sum:
                    max_index=j
                    max_sum=sumj
            index_list.append(max_index)
        return index_list
    
logistic = Logistic(x_train, y_train)
logistic.train()
#y_pred=logistic.predict(data)
y_pred=logistic.predict(x_test)
#ari_train = adjusted_rand_score(y_pred,label)
ari_train = adjusted_rand_score(y_pred,y_test)
print("ari_train = %f" % ari_train)
#cm = confusion_matrix(label,y_pred)
cm = confusion_matrix(y_test,y_pred)
plt.matshow(cm)
plt.title(u'Confusion Matrix')
plt.colorbar()
plt.ylabel(u'Groundtruth')
plt.xlabel(u'Predict')
plt.show()



#sklean的
'''x_train, x_test, y_train, y_test =\
    train_test_split(data, label, test_size=0.2, random_state=0)

scaler = StandardScaler()
x_train = scaler.fit_transform(x_train)

model = LogisticRegression(solver='liblinear', C=0.05, max_iter=150, multi_class='ovr',
                           random_state=0)
model.fit(x_train, y_train)
x_test = scaler.transform(x_test)
y_pred = model.predict(x_test)
ari_train = adjusted_rand_score(y_pred,y_test)
print("ari_train = %f" % ari_train)
cm = confusion_matrix(y_test,y_pred)
plt.matshow(cm)
plt.title(u'Confusion Matrix')
plt.colorbar()
plt.ylabel(u'Groundtruth')
plt.xlabel(u'Predict')
plt.show()'''
